package sd.settemmezzo.player.state;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;

import sd.settemmezzo.common.Player;
import sd.settemmezzo.player.state.Deck;
import sd.settemmezzo.player.state.Deck.Carta;
import sd.settemmezzo.util.Ring;

public class GlobalState extends Observable implements Serializable {
	
	private static final long serialVersionUID = -3034826842956118572L;
	
	private final static GlobalState instance = new GlobalState();
	
	private int token;
	private String message;
	
	private Ring players;

	private Player leader;
	// private Player mazziere; // ora è il leader
	
	private boolean gameStarted;

	private Map<Integer, Vector<Carta>> carte;
	private Map<Integer, Float> punteggi;
	private Map<Integer, Integer> puntate;
	private Map<Integer, Integer> soldi;
	
	private Vector<Integer> deadPlayers;

	private Deck deck;
	
	private GlobalState() {
		this.token = 0;
		this.gameStarted = false;
		this.players = new Ring();
		this.leader = new Player();
		this.carte = Collections.synchronizedMap(new HashMap<Integer, Vector<Carta>>());
		this.punteggi = Collections.synchronizedMap(new HashMap<Integer, Float>());
		this.puntate = Collections.synchronizedMap(new HashMap<Integer, Integer>());
		this.soldi = Collections.synchronizedMap(new HashMap<Integer, Integer>());
		this.deadPlayers = new Vector<Integer>();
		if (this.players.size() <= 6) {
			this.deck = new Deck();
		} else {
			this.deck = new Deck(2);
		}
	}
	
	public Deck getDeck() {
		return this.deck;
	}
	
	public void resetDeck() {
		if (this.players.size() <= 6) {
			this.deck = new Deck();
		} else {
			this.deck = new Deck(2);
		}
	}
	
	public void clearPlayer(Player p) {
		players.crash(p);
		soldi.remove(p.getId());
		puntate.remove(p.getId());
		punteggi.remove(p.getId());
		carte.remove(p.getId());
	}
	
	public Vector<Carta> getCarte(int id) {
		return carte.get(id);
	}
	
	public void resetCarte() {
		this.carte = new HashMap<Integer, Vector<Carta>>();
	}
	
	public void addCarta(int id, Carta carta) {
		if (carte.get(id) == null) {
			carte.put(id, new Vector<Carta>());
		}
		this.carte.get(id).add(carta);
	}
	
	public int getPuntata(int id) {
		if (puntate.get(id) == null) {
			return 0;
		}
		return puntate.get(id);
	}
	
	public void setPuntata(int id, int puntata) {
		this.puntate.put(id, puntata);
	}
	
	public float getPunteggio(int id) {
		if (punteggi.get(id) == null) {
			return 0;
		}
		return punteggi.get(id);
	}
	
	public void setPunteggio(int id, float punteggio) {
		this.punteggi.put(id, punteggio);
	}
	
	public int getSoldi(int id) {
		if (soldi.get(id) == null) {
			return 50;
		}
		return soldi.get(id);
	}
	
	public void setSoldi(int id, int soldi) {
		this.soldi.put(id, soldi);
	}
	
	public boolean isGameStarted() {
		return this.gameStarted;
	}
	
	public void setGameStarted() {
		this.gameStarted = true;
	}
	
	public void setGameStopped() {
		this.gameStarted = false;
	}
	
	public Ring getRing() {
		return players;
	}
	
	public void setRing(Ring playersList) {
		this.players = playersList;
	}
	
	public Player getLeader() {
		return leader;
	}
	
	public void setLeader(Player player) {
		this.leader = player;
	}
	
	public Player getMazziere() {
		//return leader;
		return players.lastElement();
	}
	
	public void setMazziere(Player mazziere) {
		this.leader = mazziere;
	}
	
	public void configMazziere(Player p) {
		players.configMazziere(p);
	}
	
	public void configMazziere(int id) {
		players.configMazziere(id);
	}
	
	public int getToken() {
		return this.token;
	}
	
	public void setToken(int token) {
		this.token = token;
	}
	
	public void addDeadPlayer(int id) {
		this.deadPlayers.add(id);
	}
	
	public boolean isDead(int id) {
		for (Integer i : deadPlayers) {
			if (i == id) return true;
		}
		return false;
	}
	
	public void setMessage(String message) {
		this.message = message;
	}

	public String getMessage() {
		return message;
	}
	
	public boolean isWinner(int id) {
		boolean result = true;
		if (soldi.get(id) != null && soldi.get(id) > 0) {
			for (Player player : players) {
				if (player.getId() == id) {
					result &= true;
				} else {
					if (soldi.get(player.getId()) > 0) {
						result &= false;
					}
				}
			}
		} else result = false;
		
		return result;
	}
	
	public int countActivePlayers() {
		int count = 0;
		for (Player p : players) {
			if (soldi.get(p.getId()) != null && 
					soldi.get(p.getId()) > 0) count++;
		}
		return count;
	}
	
	public synchronized static GlobalState getInstance() {
		return instance;
	}
	
	@Override
	public boolean equals(Object o) {
		if (o instanceof GlobalState) {
			GlobalState gs = (GlobalState)o;
			return (players.size() == gs.getRing().size() &&
					//mazziere.getId() == gs.getMazziere().getId() &&
					leader.getId() == gs.getLeader().getId()
					//carte.get(mazziere.getId()).size() == gs.carte.get(gs.mazziere.getId()).size()
					//carte.equals(gs.carte) && puntate.equals(gs.puntate) &&
					//punteggi.equals(gs.punteggi) && soldi.equals(gs.soldi) &&
					//token == gs.token && deck.equals(gs.deck)
			);
		}
		
		return false;
	}

	public void notifyChanged(Object observer) {
		this.deleteObservers();
		this.addObserver((Observer)observer);
		setChanged();
		notifyObservers();
	}

}
